//Kruskal算法求最小生成树适用于稀疏图
//运用了排序+并查集
//时间复杂度：O(mlogm)，是排序的时间复杂度
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 200010;
struct edge
{
    int a, b, w;
    //运算符重载为排序使用
    bool operator<(const edge& e) const
    {
        return w < e.w;
    }
}edges[N];
int p[N], dist[N];
int n, m;

int find(int x)
{
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin >> n >> m;
    for(int i = 0; i < m; ++i)
    {
        int a, b, w;
        cin >> a >> b >> w;
        edges[i] = {a, b, w};
    }
    //并查集开始之间需要先初始化一下p数组
    for(int i = 1; i <= n; ++i) p[i] = i;
    //进行kruskal算法
    sort(edges, edges+m);
    //cout << edges[0].w << endl;
    //遍历每条边，如果没有连上就连上
    int ret = 0, cnt = 0;
    for(int i = 0; i < m; ++i)
    {

        int a = edges[i].a, b = edges[i].b,  w = edges[i].w;
        //cout << a << ' ' << b << endl;
        int pa = find(a), pb = find(b);
        //cout << pa << ' ' << pb << endl;
        if(pa != pb) 
        {
            p[pb] = pa;
            ret += w;
            cnt++;
        }
    }
    //for(int i = 1; i <= n; ++i) cout << p[i] << endl;
    //cout << cnt << endl;
    if(cnt < n -1) cout << "impossible\n";
    else cout << ret << endl;
    return 0;
}